package com.jfinal.weixin.api;

/**
 * @author LarryKoo(larrykoo@126.com)
 * @date 2015-12-16
 */

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.utils.Exceptions;
import com.jfinal.utils.http.HttpUtil;
import com.jfinal.weixin.api.model.menu.ConditionalMenu;
import com.jfinal.weixin.api.model.menu.Menu;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * 自定义菜单管理接口
 */
@Slf4j
public enum MenuApi {
    ice;

    /**
     * ======================================================
     * ==== 自定义菜单接口可实现多种类型按钮，如下： ==============
     * ======================================================
     */
    // 1. 点击菜单拉取消息时的事件推送： CLICK
    public static final String MENU_TYPE_CLICK = "click";
    // 2. 点击菜单跳转链接时的事件推送： VIEW
    public static final String MENU_TYPE_VIEW = "view";
    // 3. scancode_push：扫码推事件
    public static final String MENU_TYPE_SCANCODE_PUSH = "scancode_push";
    // 4. scancode_waitmsg：扫码推事件且弹出“消息接收中”提示框
    public static final String MENU_TYPE_SCANCODE_WAITMSG = "scancode_waitmsg";
    // 5. pic_sysphoto：弹出系统拍照发图
    public static final String MENU_TYPE_PIC_SYSPHOTO = "pic_sysphoto";
    // 6. pic_photo_or_album：弹出拍照或者相册发图，先推送菜单事件，再推送图片消息
    public static final String MENU_TYPE_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
    // 7. pic_weixin：弹出微信相册发图器
    public static final String MENU_TYPE_PIC_WEIXIN = "pic_weixin";
    // 8. location_select：弹出地理位置选择器
    public static final String MENU_TYPE_LOCATION_SELECT = "location_select";
    // 9. media_id：下发消息（除文本消息）
    public static final String MENU_TYPE_MEDIA_ID = "media_id";
    // 10. view_limited：跳转图文消息URL
    public static final String MENU_TYPE_VIEW_LIMITED = "view_limited";

    /**
     * 自定义菜单创建
     * 请注意：
     * <p/>
     * 1、自定义菜单最多包括3个一级菜单，每个一级菜单最多包含5个二级菜单。
     * 2、一级菜单最多4个汉字，二级菜单最多7个汉字，多出来的部分将会以“...”代替。 (更正: 一级菜单7个汉字妥妥的)
     * 3、创建自定义菜单后，菜单的刷新策略是，在用户进入公众号会话页或公众号profile页时，如果发现上一次拉取菜单的请求在5分钟以前，就会拉取一下菜单;<br/>
     * 如果菜单有更新，就会刷新客户端的菜单。测试时可以尝试取消关注公众账号后再次关注，则可以看到创建后的效果。
     *
     * @param jsonMenu    自定义菜单数据json字符串
     * @param accessToken 公众号的access_token
     * @return
     */
    public ApiResult createMenu(String accessToken, String jsonMenu) {
        String url = APIConfig.WX__MENU_CREATE;
        url = url.replace("ACCESS_TOKEN", accessToken);

        if (StringUtils.isNotBlank(jsonMenu)) {
            return ApiResult.create(HttpUtil.post(url, jsonMenu));
        }
        return ApiResult.createDefault();
    }

    /**
     * 使用接口创建自定义菜单后，开发者还可使用接口查询自定义菜单的结构。
     * 另外请注意，在设置了个性化菜单后，使用本自定义菜单查询接口可以获取默认菜单和全部个性化菜单信息。
     *
     * @param accessToken 公众号的access_token
     * @return
     */
    public ApiResult getMenu(String accessToken) {
        String url = APIConfig.WX__MENU_GET;
        url = url.replace("ACCESS_TOKEN", accessToken);

        return ApiResult.create(HttpUtil.get(url));
    }

    /**
     * 自动转换自定义菜单数据为Menu对象
     *
     * @param menuData 自定义菜单Json格式数据
     * @return
     */
    public Menu convert2Menu(String menuData) {
        Menu menu = null;
        JSONObject menuJson = JSONObject.parseObject(menuData);

        try {
            //转换默认菜单数据
            if (menuJson.getJSONObject("menu") != null && !menuJson.getJSONObject("menu").isEmpty()) {
                JSONObject menuObj = menuJson.getJSONObject("menu");
                menu = JSON.parseObject(menuObj.toString(), Menu.class);

                //识别个性化菜单集数据
                if (menuJson.get("conditionalmenu") != null && menuJson.getJSONArray("conditionalmenu").size() > 0) {
                    menu.setConditionalMenu(JSON.parseArray(menuJson.getString("conditionalmenu"), ConditionalMenu.class));
                }
            }
        } catch (Exception e) {
            log.error("covert to Menu fail: {}", e);
            Exceptions.unchecked(e);
        }
        return menu;
    }

    /**
     * 使用接口创建自定义菜单后，开发者还可使用接口删除当前使用的自定义菜单。
     * 另请注意，在个性化菜单时，调用此接口会删除默认菜单及全部个性化菜单。
     *
     * @param accessToken 公众号的access_token
     * @return
     */
    public ApiResult deleteMenu(String accessToken) {
        String url = APIConfig.WX__MENU_DELETE;
        url = url.replace("ACCESS_TOKEN", accessToken);

        return ApiResult.create(HttpUtil.get(url));
    }

    /**
     * 本接口将会提供公众号当前使用的自定义菜单的配置;
     * 如果公众号是通过API调用设置的菜单，则返回菜单的开发配置，而如果公众号是在公众平台官网通过网站功能发布菜单，则本接口返回运营者设置的菜单配置。
     * <p/>
     * 请注意：
     * <p/>
     * 1、第三方平台开发者可以通过本接口，在旗下公众号将业务授权给你后，立即通过本接口检测公众号的自定义菜单配置，并通过接口再次给公众号设置好自动回复规则，以提升公众号运营者的业务体验。
     * 2、本接口与自定义菜单查询接口的不同之处在于，本接口无论公众号的接口是如何设置的，都能查询到接口，而自定义菜单查询接口则仅能查询到使用API设置的菜单配置。
     * 3、认证/未认证的服务号/订阅号，以及接口测试号，均拥有该接口权限。
     * 4、从第三方平台的公众号登录授权机制上来说，该接口从属于消息与菜单权限集。
     * 5、本接口中返回的图片/语音/视频为临时素材（临时素材每次获取都不同，3天内有效，通过素材管理-获取临时素材接口来获取这些素材）;
     * 本接口返回的图文消息为永久素材素材（通过素材管理-获取永久素材接口来获取这些素材）。
     *
     * @param accessToken 公众号的access_token
     * @return
     */
    public ApiResult getCurrentMenuInfo(String accessToken) {
        String url = APIConfig.WX__MENU_GET_CURRENT_SELF_MENU_INFO;
        url = url.replace("ACCESS_TOKEN", accessToken);

        return ApiResult.create(HttpUtil.get(url));
    }

    /**
     * ======================================================
     * ==================== 以下为个性化自定义菜单管理 ====================
     * ======================================================
     */

    /**
     * 创建个性化自定义菜单
     * 创建成功,返回自定义菜单的menuid : {"menuid":400720360}
     *
     * @param accessToken 公众号的access_token
     * @param jsonMenu    菜单JSON数据字符串
     * @return
     */
    public ApiResult createConditionalMenu(String accessToken, String jsonMenu) {
        String url = APIConfig.WX__MENU_CREATE_CONDITIONAL;
        url = url.replace("ACCESS_TOKEN", accessToken);

        if (StringUtils.isNotBlank(jsonMenu)) {
            return ApiResult.create(HttpUtil.post(url, jsonMenu));
        }
        return ApiResult.createDefault();
    }

    /**
     * 通过个性化菜单menuid删除指定的个性化菜单
     *
     * @param accessToken 公众号的access_token
     * @param menuId      menuId为菜单id，可以通过自定义菜单查询接口获取。
     * @return
     */
    public ApiResult deleteConditionalMenu(String accessToken, String menuId) {
        String url = APIConfig.WX__MENU_DELETE_CONDITIONAL;
        url = url.replace("ACCESS_TOKEN", accessToken);

        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("menuid", menuId);

        return ApiResult.create(HttpUtil.post(url, JSON.toJSONString(dataMap)));
    }

    /**
     * 测试个性化菜单匹配结果
     *
     * @param accessToken 公众号的access_token
     * @param userId      user_id可以是粉丝的OpenID，也可以是粉丝的微信号。
     * @return
     */
    public ApiResult tryMatchConditionalMenu(String accessToken, String userId) {
        String url = APIConfig.WX__MENU_TRYMATCH_CONDITIONAL;
        url = url.replace("ACCESS_TOKEN", accessToken);

        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("user_id", userId);

        return ApiResult.create(HttpUtil.post(url, JSON.toJSONString(dataMap)));
    }

}
